import { arrayTools } from '#lib';
import { cached } from '../cached.mjs';

/**
 * 通用权限管理器接口
 * 这是最顶层的抽象，不限制具体的权限类型
 * conditionInfo 使用 unknown[] 保持最大的灵活性
 */
export interface AuthManager {
  /** 权限条件信息 - 完全开放的类型，可以是任何权限条件 */
  conditionInfo: unknown;

  /**
   * 验证单个条件是否满足权限要求
   * @param condition 需要验证的条件，可以是任何类型
   * @returns 返回验证结果，true表示通过，false表示拒绝
   */
  validateCondition(condition: unknown): boolean;
}

// ==================== RBAC 基础实现 ====================

/**
 * 权限实体基类接口
 */
export interface BaseInfo {
  id: string;
  name: string;
  description?: string;
}

/**
 * RBAC 用户信息接口
 */
export interface UserInfo {
  id: string;
  name: string;
  description?: string;
  roles: RoleEntity[];
  userGroups: UserGroupEntity[];
}

/**
 * 角色实体类
 */
export class RoleEntity implements BaseInfo {
  id: string;
  name: string;
  description = '';

  constructor(info: BaseInfo) {
    if (!info?.id || !info?.name) {
      throw new Error('角色ID和名称是必需的');
    }
    Object.assign(this, info);
  }
}

/**
 * 用户组实体类
 */
export class UserGroupEntity implements BaseInfo {
  id: string;
  name: string;
  description = '';

  constructor(info: BaseInfo) {
    if (!info?.id || !info?.name) {
      throw new Error('用户组ID和名称是必需的');
    }
    Object.assign(this, info);
  }
}

/**
 * 默认实例
 */
export const defaultUserGroup = new UserGroupEntity({
  id: '0',
  name: '游客',
});

export const defaultRole = new RoleEntity({
  id: '0',
  name: '游客',
});

/**
 * 用户实体类
 */
export class UserEntity implements UserInfo {
  id: string;
  name: string;
  description = '';
  roles: RoleEntity[] = [defaultRole];
  userGroups: UserGroupEntity[] = [defaultUserGroup];

  constructor(info: UserInfo) {
    if (!info?.id || !info?.name) {
      throw new Error('用户ID和名称是必需的');
    }
    if (!Array.isArray(info.roles) || !Array.isArray(info.userGroups)) {
      throw new Error('角色和用户组必须是数组类型');
    }
    Object.assign(this, info);
  }

  setRoles(roles: RoleEntity[]) {
    if (!Array.isArray(roles)) {
      throw new Error('角色参数必须是数组类型');
    }
    this.roles = roles.length > 0 ? roles : [defaultRole];
  }

  setUserGroups(userGroups: UserGroupEntity[]) {
    if (!Array.isArray(userGroups)) {
      throw new Error('用户组参数必须是数组类型');
    }
    this.userGroups = userGroups.length > 0 ? userGroups : [defaultUserGroup];
  }

  hasRole(roleId: string): boolean {
    return this.roles.some((role) => role.id === roleId);
  }

  hasUserGroup(groupId: string): boolean {
    return this.userGroups.some((group) => group.id === groupId);
  }
}

/**
 * RBAC 权限管理器实现
 * 这是通用 AuthManager 接口的一个具体实现
 * 专门处理基于角色和用户组的权限验证
 */
export class AuthManagerEntity implements AuthManager {
  /** 权限条件信息 - 这里使用 [角色数组, 用户组数组] 的结构 */
  conditionInfo: [RoleEntity[], UserGroupEntity[]] = [[], []];

  /**
   * 构造函数
   * @param options 配置选项
   * @param options.roles 可选的角色数组
   * @param options.userGroups 可选的用户组数组
   */
  constructor(
    options: {
      roles?: RoleEntity[];
      userGroups?: UserGroupEntity[];
    } = {},
  ) {
    if (typeof options !== 'object' || options === null) {
      throw new Error('配置参数必须是对象类型');
    }

    const { roles = [], userGroups = [] } = options;

    if (!Array.isArray(roles) || !Array.isArray(userGroups)) {
      throw new Error('角色和用户组必须是数组类型');
    }

    this.conditionInfo = [roles, userGroups];
  }

  /**
   * 验证单个条件是否满足权限要求
   * 这里的实现支持角色和用户组条件
   */
  @cached
  validateCondition(condition: unknown): boolean {
    if (!condition || typeof condition !== 'object') {
      return false;
    }

    const cond = condition as { id?: string };
    if (!cond.id) {
      return false;
    }

    try {
      const [allowedRoles, allowedUserGroups] = this.conditionInfo as [
        RoleEntity[],
        UserGroupEntity[],
      ];

      // 检查是否是角色条件
      const isRoleCondition = allowedRoles.some((role) => role.id === cond.id);
      // 检查是否是用户组条件
      const isUserGroupCondition = allowedUserGroups.some(
        (group) => group.id === cond.id,
      );

      return isRoleCondition || isUserGroupCondition;
    } catch (error) {
      console.error('条件验证过程中发生错误:', error);
      return false;
    }
  }

  /**
   * 设置角色列表
   */
  setRoles(roles: RoleEntity[]) {
    if (!Array.isArray(roles)) {
      throw new Error('角色参数必须是数组类型');
    }
    (this.conditionInfo as [RoleEntity[], UserGroupEntity[]])[0] = roles;
  }

  /**
   * 设置用户组列表
   */
  setUserGroups(userGroups: UserGroupEntity[]) {
    if (!Array.isArray(userGroups)) {
      throw new Error('用户组参数必须是数组类型');
    }
    (this.conditionInfo as [RoleEntity[], UserGroupEntity[]])[1] = userGroups;
  }

  /**
   * 获取角色列表
   */
  getRoles(): RoleEntity[] {
    return [...this.conditionInfo[0]];
  }

  /**
   * 获取用户组列表
   */
  getUserGroups(): UserGroupEntity[] {
    return [...this.conditionInfo[1]];
  }
}

/**
 * 操作类型枚举
 * 定义系统中支持的标准操作类型
 */
export enum ActionType {
  /** 创建操作 */
  CREATE = 'create',
  /** 读取操作 */
  READ = 'read',
  /** 更新操作 */
  UPDATE = 'update',
  /** 删除操作 */
  DELETE = 'delete',
  /** 显示操作 */
  SHOW = 'show',
}

/**
 * 资源类型枚举
 * 定义系统中支持的资源类型，用于权限管理中的资源分类
 */
export enum ResourceType {
  /** 页面资源 */
  PAGE = 'page',
  /** 菜单资源 */
  MENU = 'menu',
  /** 按钮资源 */
  BUTTON = 'button',
  /** 操作资源 */
  ACTION = 'action',
  /** API接口资源 */
  API = 'api',
  /** 其他类型资源 */
  OTHER = 'other',
  /** 组件资源 */
  COMPONENT = 'component',
  /** 导航资源 */
  NAV = 'nav',
}

/**
 * 权限节点接口
 * 扩展基础节点，添加权限相关属性
 */
export interface PermissionNode {
  /** 节点唯一标识 */
  id: string;
  /** 节点名称 */
  name: string;
  /** 节点描述 */
  description?: string;
  resource?: ResourceType;
  /** 子节点列表 */
  children?: PermissionNode[];
  /** 父节点引用 */
  parent?: PermissionNode;
  /** 关联的操作类型 */
  action: ActionType;
}

/**
 * 权限节点实体类
 * 继承自树节点工具类，实现权限节点的树形结构
 */
export class PermissionNodeEntity
  implements arrayTools.TreeNodes<PermissionNode>
{
  value: PermissionNode[];
  rootCount: number;
  isOneRoot: boolean;
  isRoot: (node: PermissionNode) => boolean;
  traverseTree: (callback: (node: PermissionNode) => void) => void;
  getTreeDepth: () => number;
  getTreeLeaf: () => PermissionNode[];
  getTreePath: (node: PermissionNode) => PermissionNode[];
  getTreeNode: (id: string) => PermissionNode | undefined;
  getTreeLeafNodeMap: () => Map<string, PermissionNode>;
  /**
   * 创建树形结构
   * @param node 根权限节点
   * @returns 树形结构
   */
  static create(node: PermissionNode): PermissionNodeEntity {
    return arrayTools.createTreeNodes([node]);
  }
}

/**
 * 基于权限节点的权限管理器
 * 使用树形结构管理权限节点，支持层级权限验证
 */
export class PermissionBasedAuthManager implements AuthManager {
  /** 权限条件信息 - 存储权限节点树 */
  conditionInfo: PermissionNodeEntity;

  /** 内部树节点管理器 */
  private treeNodes: arrayTools.TreeNodes<PermissionNode>;

  /**
   * 构造函数
   * @param rootNode 根权限节点
   */
  constructor(rootNode: PermissionNode) {
    this.treeNodes = arrayTools.createTreeNodes([rootNode]);
    // 保持接口一致性，将树节点存储到 conditionInfo
    this.conditionInfo = this.treeNodes;
  }

  /**
   * 验证权限条件
   * @param condition 权限节点或节点ID
   * @returns 权限验证结果
   */
  @cached
  validateCondition(condition: unknown): boolean {
    try {
      let nodeId: string;

      // 类型安全的参数处理
      if (typeof condition === 'string') {
        nodeId = condition;
      } else if (
        condition &&
        typeof condition === 'object' &&
        'id' in condition
      ) {
        nodeId = (condition as PermissionNode).id;
      } else {
        return false;
      }

      // 验证节点是否存在于权限树中
      const node = this.treeNodes.getTreeNode(nodeId);
      return !!node;
    } catch (error) {
      console.error(`权限验证失败 [${String(condition)}]:`, error);
      return false;
    }
  }

  /**
   * 检查指定操作的权限
   * @param nodeId 节点ID
   * @param action 操作类型
   * @returns 是否有权限执行该操作
   */
  hasActionPermission(nodeId: string, action: ActionType): boolean {
    try {
      const node = this.treeNodes.getTreeNode(nodeId) as PermissionNode;
      if (!node) {
        return false;
      }

      // 检查节点是否支持指定操作
      return node.action === action;
    } catch (error) {
      console.error(`操作权限验证失败 [${nodeId}.${action}]:`, error);
      return false;
    }
  }

  /**
   * 获取节点信息
   * @param nodeId 节点ID
   * @returns 权限节点信息
   */
  getNode(nodeId: string): PermissionNode | null {
    try {
      return (this.treeNodes.getTreeNode(nodeId) as PermissionNode) || null;
    } catch (error) {
      console.error(`获取节点失败 [${nodeId}]:`, error);
      return null;
    }
  }

  /**
   * 获取具有指定操作权限的所有节点
   * @param action 操作类型
   * @returns 节点ID列表
   */
  getNodesByAction(action: ActionType): string[] {
    try {
      const result: string[] = [];
      // 暂时未实现，需要根据 arrayTools.TreeNodes 的具体API来实现遍历
      // 待 TreeNodes API 明确后再实现

      return result;
    } catch (error) {
      console.error(`获取操作节点失败 [${action}]:`, error);
      return [];
    }
  }
}
